#include "debug.h"
#include <string.h>
#include "stdio.h"
#include <string.h>
#include "oled.h"
#include "Delay.h"
#include "flash_ops.h"
typedef struct {
    uint8_t head;       // ?? '$'
    uint8_t ver;        // ???
    uint16_t cmd;       // ???
    uint16_t len;       // ????
    uint8_t data[256];  // ????
    uint16_t chk;       // ???
    uint8_t end[2];     // ?? "\r\n"
    uint8_t valid;      // ???????
} USART2_Frame_t;
USART2_Frame_t received_frame;

device_config_t g_device_config = {
    .product_id = "tr74iK6xFK",
    .device_name = "MSPDEV003",
    .token = "version=2018-10-31&res=products%2Ftr74iK6xFK%2Fdevices%2FMSPDEV003&et=9969688899&method=sha1&sign=pyIq%2Btd8INaurl%2F%2FU9RstKM%2BENg%3D",
    .battery_json = "{\"id\":\"123\",\"params\":{\"BatteryPercentage\":{\"value\":65}}}"
};

volatile uint8_t USART2_RX_Buffer[USART2_RX_BUF_SIZE];
volatile uint16_t USART2_RX_Index = 0;
int rx_flag = 0;

/**
  * @brief  USART2?????
  * @param  baudrate: ???,?9600?115200?
  * @retval ?
  */
void USART2_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    // 1. ????
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    
    // 2. ??GPIO
    // PA2??USART2_TX(??????)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // PA3??USART2_RX(????)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 3. ??USART2??
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);
    
    // 4. ??NVIC(?????????)
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // 5. ??USART2????
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    
    // 6. ??USART2
    USART_Cmd(USART2, ENABLE);
}

/**
  * @brief  ??????
  * @param  data: ????????
  * @retval ?
  */
void USART2_SendByte(uint8_t data)
{
    USART_SendData(USART2, data);
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}

/**
  * @brief  ?????
  * @param  str: ???????(?'\0'??)
  * @retval ?
  */
void USART2_SendString(char *str)
{
    while(*str != '\0')
    {
        USART2_SendByte(*str);
        str++;
    }
}

/**
  * @brief  ????????
  * @param  data: ????
  * @param  len: ????
  * @retval ?
  */
void USART2_SendData(uint8_t *data, uint16_t len)
{
    uint16_t i;
    for(i = 0; i < len; i++)
    {
        USART2_SendByte(data[i]);
    }
}

/**
  * @brief  USART2??????
  * @retval ?
  */
void USART2_IRQHandler(void)
{
		uint8_t receivedData;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);
        receivedData = USART_ReceiveData(USART2);      
        if(USART2_RX_Index < USART2_RX_BUF_SIZE - 1)
        {
            USART2_RX_Buffer[USART2_RX_Index++] = receivedData;
        }
        rx_flag = 1;
        
    }
}


void receive_data(void)
{	
	static int index = 0;
	static uint16_t data_index = 0;
    static uint16_t expected_len = 0;
	uint16_t i =0;
	if (rx_flag) 
	{		
		for (i = 0; i < USART2_RX_Index; i++) 
		{
			uint8_t current_byte = USART2_RX_Buffer[i];
			switch(index)
			{
				case 0:
					if(current_byte == '$')
					{
						received_frame.head = current_byte;
						USART2_SendString("Receive for frame header\r\n");
						index++;
					}			
					break;				
				case 1:
					received_frame.ver = current_byte;
					USART2_SendString("Read version number\r\n");
					index++;
					break;	
				case 2:
					received_frame.cmd = current_byte << 8;
					USART2_SendString("Read command code\r\n");
					index++;
					break;	
				case 3:
					received_frame.cmd |= current_byte;
					USART2_SendString("Read command code (second byte)\r\n");
					index++;
					break;
				case 4: // Read data length (first byte - hundreds place)
                    received_frame.len = (current_byte - '0') * 100;
					USART2_SendString("Read data length (first byte - hundreds)\r\n");
                    index++;
					break;
				case 5: // Read data length (second byte - tens place)
                    received_frame.len += (current_byte - '0') * 10;
					USART2_SendString("Read data length (second byte - tens)\r\n");
                    index++;
					break;
                case 6: // Read data length (third byte - units place)
                    received_frame.len += (current_byte - '0');
                    expected_len = received_frame.len;
                    USART2_SendString("Read data length (third byte - units)\r\n");
                    index++;
                    break;
				case 7: 
                    received_frame.data[data_index] = current_byte;
					USART2_SendByte(received_frame.data[data_index]);
					data_index++;					
                    if (data_index >= expected_len) {
                        index++;
                    }         											
					break;
				case 8:
					USART2_SendString("\r\n");	
					if(received_frame.ver == 0x31)
					{
						memcpy(g_device_config.product_id, received_frame.data, expected_len);
						USART2_SendString("Product ID updated\r\n");
					}
					else if(received_frame.ver == 0x32)
					{
						memcpy(g_device_config.device_name, received_frame.data, expected_len);
                        USART2_SendString("Device Name updated\r\n");
					}
					else if(received_frame.ver == 0x33)
					{
						memcpy(g_device_config.token, received_frame.data, expected_len);
                        USART2_SendString("Token updated\r\n");
					}
					USART2_SendString("Read data content\r\n");	
					received_frame.chk = ascii_to_hex(current_byte, 0);
                    index++;
					USART2_SendString("Read checksum (first byte)\r\n");	
					break;	
				case 9:
					received_frame.chk |= ascii_to_hex(0, current_byte);
                    index++;
					USART2_SendString("Read checksum (second byte)\r\n");	
					break;
				case 10:
					if (current_byte == '\r') {
                        received_frame.end[0] = current_byte;
                        index++;
                    } else {
                        USART2_SendString("Read frame end (first byte) error\r\n");		
                    }          
					break;
				case 11:
					if (current_byte == '\n') {
                        received_frame.end[1] = current_byte;
                        index++;
						USART2_SendString("Receive OK\r\n");	
                    } else {
                        USART2_SendString("Read frame end (secend byte) error\r\n");		
                    }          
					break;															
			}
		}
		for (i = 0; i < USART2_RX_Index; i++)
		{
			USART2_RX_Buffer[i] = 0;
		}				
		rx_flag = 0;
		index = 0;
		data_index = 0;
		expected_len = 0;
		Save_DeviceConfig_To_Flash(&g_device_config);
		OLED_ShowString(2, 1, g_device_config.token);   
		OLED_ShowString(3, 1, g_device_config.device_name);   
		OLED_ShowString(4, 1, g_device_config.product_id);
		Delay_ms(3000);   
	}
}

uint8_t ascii_to_hex(uint8_t high, uint8_t low) {
    uint8_t result = 0;
    if (high >= '0' && high <= '9') result = (high - '0') << 4;
    else if (high >= 'A' && high <= 'F') result = (high - 'A' + 10) << 4;
    
    if (low >= '0' && low <= '9') result |= (low - '0');
    else if (low >= 'A' && low <= 'F') result |= (low - 'A' + 10);
    
    return result;
}
